#include "../head/server.h"

TCP_info_t TCP_info[MAX_TCPS]; // 存TCP连接活动信息的数组

int main(int argc, char *argv[])
{
	// ./server ip 端口号 子线程数目
	// ARGS_CHECK(argc, 4);

	// 从配置文件中加载服务器ip
	char ip[100] = {0};
	getparameter("ip", ip); // tools.c
	printf("ip: %s\n", ip);
	// 从配置文件中加载服务器端口
	char port[100] = {0};
	getparameter("port", port); // tools.c
	printf("port: %s\n", port);
	// 从配置文件中加载子线程数量
	char threadNum[100] = {0};
	getparameter("threadNum", threadNum); // tools.c
	printf("threadNum: %s\n", threadNum);

	// 从配置文件中读取出连接数据库所需的数据
	char mysql_user[100] = {0};
	getparameter("mysql_user", mysql_user); // tools.c
	// printf("mysql_user: %s\n", mysql_user);
	char mysql_password[100] = {0};
	getparameter("mysql_password", mysql_password); // tools.c
	// printf("mysql_password: %s\n", mysql_password);
	char mysql_database[100] = {0};
	getparameter("mysql_database", mysql_database); // tools.c
	// printf("mysql_database: %s\n", mysql_database);

	MYSQL *mysql = mysql_init(NULL);
	MYSQL *ret = mysql_real_connect(
		mysql,
		"localhost",
		mysql_user,
		mysql_password,
		mysql_database,
		0, NULL, 0);
	if (ret == NULL)
	{
		fprintf(stderr, "mysql_real_connect:%s\n", mysql_error(mysql));
	}

	int i;
	for (i = 0; i < MAX_TCPS; i++)
	{
		TCP_info[i].net_fd = -1;
		TCP_info[i].last_activity = 0;
		bzero(TCP_info[i].username, sizeof(TCP_info[i].username));
	}

	threadPool_t threadPool;
	// 初始化线程池和任务队列
	initThreadPool(&threadPool, atoi(threadNum)); // initThreadPool.c

	int socket_fd;
	// 初始化socket连接
	initTcpSocket(&socket_fd, ip, port); // initTcpSocket.c
	printf("初始socket_fd: %d\n", socket_fd);

	int epoll_fd = epoll_create(1);

	// 创建一个专门用来轮询TCP连接是否超时的子线程
	pthread_t ask_tid;
	pthread_create(&ask_tid, NULL, ask_thread, &epoll_fd);

	// 添加socket_fd到epoll
	epollAddFD(epoll_fd, socket_fd); // epoll.c

	// 用来获取客户端的地址信息
	struct sockaddr_in clientAddr;
	// 客户端地址信息结构体大小
	socklen_t clientAddrLength = sizeof(clientAddr);
	NETDISK_LOG_INFO(socket_fd, clientAddr);

	struct epoll_event readyset[1024];
	while (1)
	{
		int readynum = epoll_wait(epoll_fd, readyset, 1024, -1);
		for (int i = 0; i < readynum; ++i)
		{
			if (readyset[i].data.fd == socket_fd)
			{
				printf("socket_fd: %d\n", readyset[i].data.fd);
				int net_fd = accept(socket_fd, (struct sockaddr *)&clientAddr, &clientAddrLength);
				printf("产生一个新的net_fd: %d\n", net_fd);
				NETDISK_LOG_INFO(net_fd, clientAddr);

				// 更新TCP_info
				TCP_info[net_fd].net_fd = net_fd;
				time_t current_time = time(NULL);
				TCP_info[net_fd].last_activity = current_time;

				train_t train;
				bzero(&train, sizeof(train));
				// 接收客户端消息，用来判断是长连接还是短连接
				char conn_msg[1024] = {0};
				recv(net_fd, &train.length, sizeof(train.length), MSG_WAITALL);
				recv(net_fd, train.data, train.length, MSG_WAITALL);
				memcpy(conn_msg, train.data, train.length);
				printf("msg: %s\n", conn_msg);
				if (!strcmp(conn_msg, "short"))
				{										  // 短命令
					int res = user_verify(net_fd, mysql); // user.c
					if (res == 0)
					{
						printf("将netfd: %d加入监听\n", net_fd);
						epollAddFD(epoll_fd, net_fd);
					}
				}
				else
				{ // 长命令
					// int long_fd = accept(socket_fd, (struct sockaddr *)&clientAddr, &clientAddrLength);
					int long_fd = net_fd;
					printf("用于通信的long_fd: %d\n", long_fd);
					NETDISK_LOG_INFO(long_fd, clientAddr);

					char username[1024] = {0};
					bzero(&train, sizeof(train));
					// 接收用户名
					recv(long_fd, &train.length, sizeof(train.length), MSG_WAITALL);
					recv(long_fd, train.data, train.length, MSG_WAITALL);
					memcpy(username, train.data, train.length);
					printf("用户发送过来的验证身份的用户名：%s\n", username);
					// 根据用户名使用jwt加密生成token
					char token[4096] = {0};
					jwt_encode(token, username);

					bzero(&train, sizeof(train));
					// 用户发送的token
					recv(long_fd, &train.length, sizeof(train.length), MSG_WAITALL);
					recv(long_fd, train.data, train.length, MSG_WAITALL);
					printf("用户发送过来的验证身份的token：%s\n", train.data);
					// 根据token验证用户身份
					if (!strcmp(token, train.data)) // 验证成功
					{
						printf("验证成功\n");
						bzero(&train, sizeof(train));
						train.length = strlen("verify_success");
						memcpy(train.data, "verify_success", train.length);
						send(long_fd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
						pthread_mutex_lock(&threadPool.taskQueue.mutex);
						enQueue(&threadPool.taskQueue, long_fd);
						pthread_cond_signal(&threadPool.taskQueue.cond);
						pthread_mutex_unlock(&threadPool.taskQueue.mutex);
					}
					else // 验证失败
					{
						printf("验证失败\n");
						bzero(&train, sizeof(train));
						train.length = strlen("verify_fail");
						memcpy(train.data, "verify_fail", train.length);
						send(long_fd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
						close(long_fd);
					}
				}
			}
			else
			{
				// 处理短命令
				printf("用于通信的net_fd: %d\n", readyset[i].data.fd);

				TCP_info[readyset[i].data.fd].net_fd = readyset[i].data.fd;
				time_t current_time = time(NULL);
				TCP_info[readyset[i].data.fd].last_activity = current_time;

				train_t train;
				bzero(&train, sizeof(train));

				// 接收用户名
				/* recv(readyset->data.fd, &train.length, sizeof(train.length), MSG_WAITALL);
				recv(readyset->data.fd, &train.data, train.length, MSG_WAITALL);
				char username[1024] = {0};
				memcpy(username, train.data, train.length);
				bzero(&train, sizeof(train)); */

				// 接收cmd
				recv(readyset->data.fd, &train.length, sizeof(train.length), MSG_WAITALL);
				if (train.length == 0)
				{
					printf("用户 %s 断开连接\n", TCP_info[readyset->data.fd].username);
					epollDelFD(epoll_fd, readyset->data.fd);
					TCP_info[readyset->data.fd].net_fd = -1;
					bzero(TCP_info[readyset->data.fd].username, sizeof(TCP_info[readyset->data.fd].username));
					close(readyset->data.fd);
					break;
				}
				recv(readyset->data.fd, &train.data, train.length, MSG_WAITALL);
				char cmd[60] = {0};
				memcpy(cmd, train.data, train.length);

				// 接收用户名
				bzero(&train, sizeof(train));
				recv(readyset->data.fd, &train.length, sizeof(train.length), MSG_WAITALL);
				recv(readyset->data.fd, &train.data, train.length, MSG_WAITALL);
				char username[1024] = {0};
				memcpy(username, train.data, train.length);

				printf("来自用户 %s 的 %s 指令\n", username, cmd);

				int netfd = readyset->data.fd;
				// 判断命令
				if (!strcmp(cmd, "cd"))
				{ // 切换目录
					// 调用cd处理函数
					cd_work(netfd, username, mysql);
				}
				else if (!strcmp(cmd, "ls"))
				{ // 显示当前目录下所有文件的名字
					// 调用ls处理函数
					ls_work(netfd, username, mysql);
				}
				else if (!strcmp(cmd, "remove"))
				{ // 删除指定文件
					// 调用remove处理函数
					remove_work(netfd, username, mysql);
				}
				else if (!strcmp(cmd, "pwd"))
				{ // 显示当前路径
					// 调用pwd处理函数
					pwd_work(netfd, username, mysql);
				}
			}
		}
	}

	close(epoll_fd);
	close(socket_fd);

	return 0;
}